#include "bsp_mq2.h"

#include <math.h>

#include "lz_hardware.h"

#include "los_task.h"

#define MQ2_ADC_CHANNEL         4

static DevIo mq2_adcInitStruct = {
    .isr = {.gpio = INVALID_GPIO},
    .rst = {.gpio = INVALID_GPIO},
    .ctrl1 = {  
        .gpio = GPIO0_PC4, 
        .func = MUX_FUNC1, 
        .type = PULL_NONE, 
        .drv = DRIVE_KEEP, 
        .dir = LZGPIO_DIR_IN,
        .val = LZGPIO_LEVEL_KEEP
    },
    .ctrl2 = {.gpio = INVALID_GPIO}
};

int mq2_init(void)
{
    unsigned int ret = 0;

    ret = DevIoInit(mq2_adcInitStruct);
    if(ret != LZ_HARDWARE_SUCCESS)
    {
        printf("%s, %s, %d: ADC(mq2) Key IO Init fail\n", __FILE__, __func__, __LINE__);
        return -1;
    }

    //在 bsp_key 的init 中已经初始化了
    // ret = LzSaradcInit();

    return 0;
}

//获取电压值
static float Adc_get_vol()
{
    unsigned int ret = LZ_HARDWARE_SUCCESS;
    uint32_t raw;
    // uint32_t sum = 0;
    // int i = 0;
    
    // TODO: 均值滤波 
    ret = LzSaradcReadValue(MQ2_ADC_CHANNEL, &raw);
    if(ret != LZ_HARDWARE_SUCCESS)
    {
        printf("%s, %s, %d: ADC Read Fail\n", __FILE__, __func__, __LINE__);
        return 0.0;
    }

    return (float)(raw * 3.3f / 1024.0f);
}

const float Vc = 5.0f;    // 传感器供电电压
const float RL = 5.0e3f;  // 负载电阻5kΩ

static float Compute_Rs(float Vout)
{
    return (Vc - Vout) / Vout * RL;
}

static float default_R0 = 0;
//预先校准R0（洁净空气值）
float mq2_calibrate_R0(void)
{
    float sum = 0;
    for(int i = 0; i < 100; i++)
    {
        sum += Compute_Rs(Adc_get_vol());
        LOS_Msleep(10);
    }

    default_R0 = sum / 100.0f;

    return default_R0;
}

//计算烟雾浓度(ppm)
static float Compute_smoke_PPM(float Rs, float R0)
{
    const float a = 3000.0f;    //烟雾参数
    const float b = -1.6f;
    return a * powf(Rs/R0, b);
}

//温湿度补偿
static float Compensate_PPM(float ppm, float temp_C, float humidity)
{
    const float alpha = 0.02f;
    const float beta = 0.0015f;
    return ppm / (1 + alpha*(temp_C-25) + beta*(humidity-50));
}

// #define FILTER_SIZE     10
// float mq2_filtered_PPM()
// {
//     static float buf[FILTER_SIZE];
//     static int idx = 0;

//     buf[idx] = mq2_compute_smoke_PPM(...);
//     idx = (idx + 1) % FILTER_SIZE;

//     float sum = 0;
//     for(int i = 0; i < FILTER_SIZE; i++) sum += buf[i];
//     return sum / FILTER_SIZE;
// }

float mq2_get_ppm(void)
{
    // default_R0 = mq2_calibrate_R0();

    float Vout = Adc_get_vol();
    float Rs = Compute_Rs(Vout);
    float ppm = Compute_smoke_PPM(Rs, default_R0);

    return ppm;
}

#define MQ2_READ_TIMES      10

float mq2_get_ppm_tow(void)
{
    float  tmp = 0;
	
 
	for (uint8_t i = 0; i < MQ2_READ_TIMES; i++)
	{
		tmp += Adc_get_vol();
		LOS_Msleep(5);
	}
	tmp /= MQ2_READ_TIMES;
	
	float Vol = tmp;
	float RS = (5-Vol)/(Vol*0.5);
	float R0=6.64;
	
	float ppm = pow(11.5428*R0/RS, 0.6549f);
	
	return ppm;
}
